package net.woggle.shackbrowse;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import net.woggle.shackbrowse.NetworkNotificationServers.OnGCMInteractListener;
import net.woggle.shackbrowse.SlideFrame.OnInteractListener;
import net.woggle.shackbrowse.ThreadListFragment.ThreadLoadingAdapter;
import net.woggle.shackbrowse.notifier.NotifierReceiver;
import net.woggle.shackbrowse.notifier.NotifierService;

import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.provider.ContactsContract.Data;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.PagerTitleStrip;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.Editable;
import android.text.Html;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.app.SherlockListFragment;
import com.google.analytics.tracking.android.EasyTracker;
import com.google.analytics.tracking.android.Tracker;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.viewpagerindicator.TitlePageIndicator;
import com.viewpagerindicator.TitlePageIndicator.LinePosition;

public class MainActivity extends SherlockFragmentActivity
{

	SbFragmentAdapter mAdapter;
    ViewPager mPager;
    OfflineThread mOffline;
    //PagerTabStrip mIndicator;
    
    public SearchResultFragment _searchResults;
    public ThreadViewFragment _threadView;
    int _splitView = 1;
    boolean _dualPane = false;
	private int _orientLock = 0;
	private Dialog _mOpenDialog = null;
	SharedPreferences _prefs;
	private ArrayList<Integer> _threadIdBackStack = new ArrayList<Integer>();
	private int _lastX = 0;
	SlideFrame _tviewFrame;
	SlideFrame _sresFrame;
	public boolean _analytics = true;
	private Tracker myTracker;
	
	public Boolean _messagesGetInbox = true;
	protected boolean _nextBackQuitsBecauseOpenedAppViaIntent = false;
	private float _zoom = 1.0f;
	private LinearLayout _menuFrame;
	private AppMenu _appMenu;
	boolean _showFavorites = false;
	boolean _showPinnedInTL = true;
	private long _lastOpenedThreadViewEpochSeconds = 0l;
	
	boolean _swappedSplit = false;
	private boolean _enableKeywordFilter = false;
	Seen _seen;
	NetworkNotificationServers _GCMAccess;
	private TitlePageIndicator titleIndicator;
	private ThreadListFragment _threadList;
	private MessageFragment _messageList;
	private SearchView _searchView;
	    
	    
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		
		if (savedInstanceState != null)
		{
			// save state stuff
			System.out.println("STATE RECEIVED");
		}
		
		this.setContentView(R.layout.main_splitview);
		
		getWindow().setBackgroundDrawableResource(R.drawable.bg_app_ics);
		
		_prefs = PreferenceManager.getDefaultSharedPreferences(this);
		
		// this is for upgraders, a check to upgrade donator prefs
		upgradeDonatorPreferences();
				
		// set up preferences
		_analytics  = _prefs.getBoolean("analytics", true);
		_zoom  = Float.parseFloat(_prefs.getString("fontZoom", "1.0"));
		_showFavorites  = _prefs.getBoolean("showFavorites", false);
		_showPinnedInTL  = _prefs.getBoolean("showPinnedInTL", true);
		_swappedSplit  = _prefs.getBoolean("swappedSplit", false);
		_enableKeywordFilter = _prefs.getBoolean("enableDonatorFeatures", false);
		
		// notifications registrator, works mostly automatically
		
		OnGCMInteractListener GCMlistener = new OnGCMInteractListener(){@Override	public void networkResult(String res) {
			// this allows the check mark to be placed when push notifications are automatically enabled if the setting has never been touched
			Editor edit = _prefs.edit();
			if (res.contains("SLOW REG"))
			{
				edit.putBoolean("slowNotification", true);
				edit.putBoolean("fastNotification", false);
				System.out.println("PUSHREG: SET SLOW REG AUTO");
			}
			edit.commit();
		}};
		_GCMAccess = new NetworkNotificationServers(this, GCMlistener);
		// this pref is OPT OUT
		if (!_prefs.contains("slowNotification"))
    	{
			_GCMAccess.doRegisterTask("reg");
    	}
		
		
		
		// seen
		_seen = new Seen();

		
		// set up fragments
		FragmentManager fm = getSupportFragmentManager();
		FragmentTransaction ft = fm.beginTransaction();
		_threadView = (ThreadViewFragment)Fragment.instantiate(getApplicationContext(), ThreadViewFragment.class.getName(), new Bundle());
		ft.add(R.id.singleThread, _threadView);
		ft.attach(_threadView);
		ft.commit();
		
		ft = fm.beginTransaction();
		_searchResults = (SearchResultFragment)Fragment.instantiate(getApplicationContext(), SearchResultFragment.class.getName(), new Bundle());
		ft.add(R.id.searchResults, _searchResults);
		ft.attach(_searchResults);
		ft.commit();
		
		ft = fm.beginTransaction();
		_threadList = (ThreadListFragment)Fragment.instantiate(getApplicationContext(), ThreadListFragment.class.getName(), new Bundle());
		ft.attach(_threadList);
		ft.commit();
		
		ft = fm.beginTransaction();
		_messageList = (MessageFragment)Fragment.instantiate(getApplicationContext(), MessageFragment.class.getName(), new Bundle());
		ft.attach(_messageList);
		ft.commit();
		
		ft = fm.beginTransaction();
		_searchView = (SearchView)Fragment.instantiate(getApplicationContext(), SearchView.class.getName(), new Bundle());
		ft.attach(_searchView);
		ft.commit();
		
		// set up landscape mode navigation
		evaluateDualPane(getResources().getConfiguration());
		
		// menu setup
		_appMenu = (AppMenu)getSupportFragmentManager().findFragmentById(R.id.appMenuFragment);
				
		
		// setup viewpager
        mAdapter = new SbFragmentAdapter(getSupportFragmentManager());

        this.getSupportActionBar().hide();
        mPager = (ViewPager)findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);
        
        mPager.setCurrentItem(1);
        
        //Bind the title indicator to the adapter
        titleIndicator = (TitlePageIndicator)findViewById(R.id.titles);
        titleIndicator.setViewPager(mPager);
        titleIndicator.setBackgroundResource(R.color.app_bg_color);
        titleIndicator.setFooterColor(this.getResources().getColor(R.color.buttonBarHighLight));
        //titleIndicator.setsetTabIndicatorColor(this.getResources().getColor(R.color.buttonBarHighLight));
        titleIndicator.setTextSize(30 * _zoom);
        titleIndicator.setLinePosition(LinePosition.Top);

        // set up pager indicator
        /*
        mIndicator = (PagerTabStrip) findViewById(R.id.pager_header);
        mIndicator.setDrawFullUnderline(true);
        mIndicator.setBackgroundResource(R.color.buttonBarBg);
        mIndicator.setTabIndicatorColor(this.getResources().getColor(R.color.buttonBarHighLight));
        mIndicator.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16 * _zoom);
        */
        // set up favorites class
        mOffline = new OfflineThread(this);
        
        // setup auto load of favorites
        //continued from above
        
        // animnate titles
        
        
        titleIndicator.setOnPageChangeListener(new OnPageChangeListener(){
        // mPager.setOnPageChangeListener(new OnPageChangeListener(){

			@Override
			public void onPageScrollStateChanged(int arg0) {
				// TODO Auto-generated method stub
				closeMenu();
				
				if (arg0 == ViewPager.SCROLL_STATE_IDLE)
				{
					titleIndicator.postDelayed(new Runnable(){@Override	public void run() { 
						AlphaAnimation anim = new AlphaAnimation(1f,0f);
						anim.setDuration(250);
						anim.setAnimationListener(new AnimationListener(){
							@Override
							public void onAnimationEnd(Animation arg0) {
								titleIndicator.setVisibility(View.GONE);
							}
							@Override
							public void onAnimationRepeat(Animation arg0) {}
							@Override
							public void onAnimationStart(Animation arg0) {}
						});
						titleIndicator.startAnimation(anim);
						
					}}, 400);
				}
				if (arg0 == ViewPager.SCROLL_STATE_DRAGGING)
				{
					titleIndicator.setVisibility(View.VISIBLE);
					AlphaAnimation anim = new AlphaAnimation(0f,1f);
					anim.setDuration(100);
					titleIndicator.startAnimation(anim);
				}
				
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onPageSelected(int arg0) {
				
				_appMenu.setPageId(arg0);
				
				if (arg0 == 2)
				{
					// offlinethreadfrag
					mRefreshOfflineThreads();
				}
				if (arg0 != 0)
				{
					// auto close keyboard if not on search page
					hideKeyboard();
				}
				if (isMessagesShowing())
				{
					if ((getMessageFragment() != null) && (getMessageFragment()._adapter != null) && (getMessageFragment()._adapter.getCount() == 0))
						refreshMessages();
				}
			}
        });
        
        // set up change log
        ChangeLog cl = new ChangeLog(this);
        if (cl.firstRun())
            cl.getLogDialog().show();
        
        // set up donator icons
        new LimeTask().execute();
        
        // initialize slide frame handle
        _tviewFrame = ((SlideFrame)findViewById(R.id.singleThread));
        _sresFrame = ((SlideFrame)findViewById(R.id.searchResults));
        _menuFrame = ((LinearLayout)findViewById(R.id.appMenu));
        
        _tviewFrame.setOnInteractListener(new SlideFrame.OnInteractListener() {
			
			@Override
			public void onOpened() {
				// TODO Auto-generated method stub
				if (!getDualPane())
				{
					mPager.setVisibility(View.GONE);
					_sresFrame.setVisibility(View.GONE);
				}
			}
			
			@Override
			public void onOpen() {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onClosed() {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onClose() {
				// user closed thread slider, so doesnt want to go back to previous app
				_nextBackQuitsBecauseOpenedAppViaIntent = false;
				_threadList._nextBackQuitsBecauseOpenedAppViaIntent = false;
				
				if (_sresFrame.isOpened())
					mPager.setVisibility(View.GONE);
				else
					mPager.setVisibility(View.VISIBLE);
				_sresFrame.setVisibility(View.VISIBLE);
			}
			public void onDrag()
			{
				if (_sresFrame.isOpened())
					mPager.setVisibility(View.GONE);
				else
					mPager.setVisibility(View.VISIBLE);
				_sresFrame.setVisibility(View.VISIBLE);
			}
			
		});
        _sresFrame.setOnInteractListener(new SlideFrame.OnInteractListener() {
			
			@Override
			public void onOpened() {
				// TODO Auto-generated method stub
				if (!getDualPane())
				{
					mPager.setVisibility(View.GONE);
				}
			}
			
			@Override
			public void onOpen() {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onClosed() {
			}
			
			@Override
			public void onClose() {
				mPager.setVisibility(View.VISIBLE);
			}
			public void onDrag()
			{
				mPager.setVisibility(View.VISIBLE);
			}
		});
        
        _sresFrame.setSlidingEnabled(true);
        
        // fade out titles
        titleIndicator.postDelayed(new Runnable(){@Override	public void run() { 
			AlphaAnimation anim = new AlphaAnimation(1f,0f);
			anim.setDuration(250);
			anim.setAnimationListener(new AnimationListener(){
				@Override
				public void onAnimationEnd(Animation arg0) {
					titleIndicator.setVisibility(View.GONE);
				}
				@Override
				public void onAnimationRepeat(Animation arg0) {}
				@Override
				public void onAnimationStart(Animation arg0) {}
			});
			titleIndicator.startAnimation(anim);
			
		}}, 1700);
        
        // check for wifi connection
        ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
        NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        // check for shack messages
        if (mWifi.isConnected() || _prefs.getBoolean("SMCheckOnCellNotification", false)) {
        	new CheckForSMTask().execute();
        }
        
        // external intent handling
        Intent intent = getIntent();
        if (intent != null)
        	handleIntent(intent);
	}

	// used for sending fake notifications to the notifierreceiver. check for sms locally, then send notification!
	private void sendSMBroadcast(String username, String text, int nlsid, boolean multiple, int howMany) {
		NotifierReceiver receiver = new NotifierReceiver();
		registerReceiver( receiver, new IntentFilter( "net.woggle.fakenotification" ) );
		
		Intent broadcast = new Intent();
		broadcast.putExtra("type", "shackmsg");
		broadcast.putExtra("username", (multiple) ? "multiple" : username);
		broadcast.putExtra("text", (multiple) ? Integer.toString(howMany) : text);
		broadcast.putExtra("nlsid", Integer.toString(nlsid));
        broadcast.setAction("net.woggle.fakenotification");
        sendBroadcast(broadcast);
        
       // unregisterReceiver(receiver);
	}

	protected void hideKeyboard() {
		final InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mPager.getWindowToken(), 0);
	}

	@Override
	protected void onDestroy () {
		super.onDestroy();
		mOffline.endCloudUpdates();
	}
	
	public void toggleMenu() {
		if (_menuFrame.getVisibility() == View.GONE)
			openMenu();
		else
			closeMenu();
	}
	
	public void openMenu() {
		if (_menuFrame.getVisibility() == View.GONE)
		{
			_appMenu.updateMenuUi();
			_menuFrame.setVisibility(View.VISIBLE);
			AlphaAnimation anim = new AlphaAnimation(0f,1f);
			anim.setDuration(100);
			_menuFrame.startAnimation(anim);
		}
	}
	public boolean isMenuOpen() {
		if (_menuFrame.getVisibility() == View.VISIBLE)
		{
			return true;
		}
		else return false;
	}
	
	public void closeMenu() {
		if (_menuFrame.getVisibility() == View.VISIBLE)
		{
			AlphaAnimation anim = new AlphaAnimation(1f,0f);
			anim.setDuration(100);
			anim.setAnimationListener(new AnimationListener(){
				@Override
				public void onAnimationEnd(Animation arg0) {
					_menuFrame.setVisibility(View.GONE);
				}
				@Override
				public void onAnimationRepeat(Animation arg0) {}
				@Override
				public void onAnimationStart(Animation arg0) {}
			});
			_menuFrame.startAnimation(anim);
		}
	}
	
	
	private String pageIdToString(int arg0) {
		switch (arg0)
		{
			case 0: return "Search";
			case 1: return "Latest Chatty";
			case 2: if (_showFavorites) return "Favorites";
			case 3:
				if (_messagesGetInbox)
					return "Message Inbox";
				else
					return "Sent Messages";
		}
		return null;
	}

	// FRAGMENT COMMAND SENDING AREA
	public void openComposer (int returnResultType, String preText)
	{
		Intent i = new Intent(this, ComposePostView.class);
		if (preText != null)
			{ i.putExtra("preText", preText); }
        startActivityForResult(i, returnResultType);
	}
	public void openComposerAndUploadImage (int returnResultType, Uri preImage)
	{
		Intent i = new Intent(this, ComposePostView.class);
		i.putExtra("preImage", preImage);
        startActivityForResult(i, returnResultType);
	}
	final static String THREAD_ID = "threadid";
	final static String IS_NEWS_ITEM = "isnewsitem";
	public void openComposerForReply (int returnResultType, Post parentPost, boolean isNewsItem)
	{
		Intent i = new Intent(this, ComposePostView.class);
        i.putExtra(THREAD_ID, parentPost.getPostId());
        i.putExtra("parentAuthor", parentPost.getUserName());
        i.putExtra("parentContent", parentPost.getContent());
        i.putExtra("parentDate", parentPost.getPosted());
        i.putExtra(IS_NEWS_ITEM, isNewsItem);
        startActivityForResult(i, returnResultType);
	}
	
	public void openComposerForMessageReply (int returnResultType, Post parentPost, String messageSubject)
	{
		Intent i = new Intent(this, ComposePostView.class);
        i.putExtra("mode", "message");
        i.putExtra("parentAuthor", parentPost.getUserName());
        i.putExtra("parentContent", parentPost.getCopyText());
        i.putExtra("messageSubject", messageSubject);
        startActivityForResult(i, returnResultType);
	}
	public void openNewMessagePromptForSubject (final String username)
	{
    	boolean verified = _prefs.getBoolean("usernameVerified", false);
        if (!verified)
        {
        	LoginForm login = new LoginForm(this);
        	login.setOnVerifiedListener(new LoginForm.OnVerifiedListener() {
				@Override
				public void onSuccess() {
					openNewMessagePromptForSubject(username);
				}

				@Override
				public void onFailure() {
				}
			});
        	return;
        }
    	AlertDialog.Builder alert = new AlertDialog.Builder(this);
    	alert.setTitle("Shackmessage to " + username);
    	alert.setMessage("Subject:");
    	final EditText input = new EditText(this);
    	alert.setView(input);
    	alert.setPositiveButton("Next", new DialogInterface.OnClickListener() {
    	public void onClick(DialogInterface dialog, int whichButton) {
			Editable value = input.getText();
			Post post = new Post(0, username, "", null, 0, "", false);
			openComposerForMessageReply(ThreadViewFragment.POST_MESSAGE, post, value.toString());
    	}});
    	alert.setNegativeButton("Cancel", null);
    	alert.show();
	}
	
	public void openThreadView(int threadId) { openThreadView(threadId, null, 0, null, false, 0, null, false, false); }
	public void openThreadView(int threadId, Thread thread, LolObj lol) {
		Post post = Post.fromThread(thread);
		post.setLolObj(lol);
		openThreadView(threadId, post, 0, thread.getJson().toString(), false, 0, null, false, false);
	}
	public void openThreadViewAndSelect(int selectPostIdAfterLoading) {	openThreadView(selectPostIdAfterLoading, null, selectPostIdAfterLoading, null, false, 0, null, false, true);	}
	public void openThreadViewAndSelectWithBackStack(int selectPostIdAfterLoading) {
		openThreadView(selectPostIdAfterLoading, null, selectPostIdAfterLoading, null, false, 0, null, true, true);
	}
	public void openThreadViewAndFave(int faveThreadId)	{ openThreadView(faveThreadId, null, 0, null, true, 0, null, false, false); }
	public void openMessageView(int messageId, Message message)	{ openThreadView(0, Post.fromMessage(message), 0, null, false, messageId, message.getSubject(), false, false); }
	public void openThreadView(int threadId, Post post, int selectPostIdAfterLoading, String json, boolean autoFaveOnLoad, int messageId, String messageSubject, boolean preserveBackStack, boolean doesntExpire)
	{
		boolean expired = false;
		long current = (System.currentTimeMillis() / 1000);
		
		// threadview data expires after 3 minute
		if ((_lastOpenedThreadViewEpochSeconds > 0) && ((current - _lastOpenedThreadViewEpochSeconds) > 60))
			expired = true;
		
		if (doesntExpire)
			expired = false;
		
		_lastOpenedThreadViewEpochSeconds = current;
		hideKeyboard();
        ThreadViewFragment view = _threadView;
        if ((!view.isPostIdInAdapter(threadId) || expired) || (view._messageId != messageId))
        {
        	view._rootPostId = threadId;
        	view._currentPostId = view._rootPostId;
        	view._messageId = messageId;
        	view._selectPostIdAfterLoading = selectPostIdAfterLoading;
        	view._autoFaveOnLoad = autoFaveOnLoad;
        	view._messageSubject = messageSubject;
        	
        	if (view._adapter != null)
        	{
	        	view._adapter.clear();
	        	view._adapter.triggerLoadMore();
        	}
        	
        	if (post != null)
        		view.loadPost(post);
        	
            if (json != null)
            {
            	try {
					view._lastThreadJson = new JSONObject(json);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }
            else
            	view._lastThreadJson = null;
        	
            view.updateMessageReplyButton();
            view.updateThreadViewUi();
        }
        else if (view.isPostIdInAdapter(threadId))
        {
        	view.ensurePostSelectedAndDisplayed(threadId);
        }
        if (!preserveBackStack)
        {
        	this.resetThreadIdBackStack();
        }
        
        _tviewFrame.openLayer(true);
        _appMenu.updateMenuUi();
	}
	
	public void mRefreshOfflineThreads()
    {
		if (_showFavorites)
		{
			FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
			OfflineThreadFragment otf = (OfflineThreadFragment) a.instantiateItem(mPager, 2);
			otf.refreshOfflineThreads();
    	}
    }
	
    public void mRefreshOfflineThreadsWoReplies()
    {
    	if (_showFavorites)
		{
			FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
			OfflineThreadFragment otf = (OfflineThreadFragment) a.instantiateItem(mPager, 2);
			otf.updateThreadsWithoutUpdateReplies();
		}
/*
		FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
		ThreadListFragment tlf = (ThreadListFragment) a.instantiateItem(mPager, 1); */
		if (_threadList._adapter != null)
			_threadList._adapter.notifyDataSetChanged();
    }
    
    public void markFavoriteAsRead(int _rootPostId, int count) {
        if ((mOffline != null) && (mOffline.containsThreadId(_rootPostId)))
        {
	    	if (_showFavorites)
			{
				FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
				OfflineThreadFragment otf = (OfflineThreadFragment) a.instantiateItem(mPager, 2);
				otf.markFavoriteAsRead(_rootPostId, count);
			}
	    	if (_showPinnedInTL)
	    	{
				_threadList.markFavoriteAsRead(_rootPostId, count);
		    }
	    	
            // update data for last viewed count, this creates the info for how many are unread.
	    	mOffline.updateRecordedReplyCountPrev(_rootPostId, count);
            
            // update "previous" count
	    	mOffline.updateRecordedReplyCount(_rootPostId, count);
	    	mOffline.flushThreadsToDiskTask();
        }
    	mRefreshOfflineThreadsWoReplies();
	}
    
    public void mOfflineThreadsNotifyAdapter()
    {
    	if (_showFavorites)
		{
			FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
			OfflineThreadFragment otf = (OfflineThreadFragment) a.instantiateItem(mPager, 2);
			otf._doNotGetReplies = true;
			if (otf._adapter != null)
				otf._adapter.triggerLoadMore();
		}
    	if (_showPinnedInTL)
    	{
    		/*
			FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
			ThreadListFragment TLfragment = (ThreadListFragment) a.instantiateItem(mPager, 1);
			*/
			if (_threadList._adapter != null)
				_threadList._adapter.silentUpdatePinned();
	    }
    }
    
    public void switchMessageType()
    {
    	
    	// show the change with animation
    	titleIndicator.setVisibility(View.VISIBLE);
		AlphaAnimation anim = new AlphaAnimation(0f,1f);
		anim.setDuration(100);
		anim.setAnimationListener(new AnimationListener(){
			@Override
			public void onAnimationEnd(Animation arg0) {
				titleIndicator.postDelayed(new Runnable(){@Override	public void run() { 
					AlphaAnimation anim = new AlphaAnimation(1f,0f);
					anim.setDuration(400);
					anim.setAnimationListener(new AnimationListener(){
						@Override
						public void onAnimationEnd(Animation arg0) {
							titleIndicator.setVisibility(View.GONE);
						}
						@Override
						public void onAnimationRepeat(Animation arg0) {}
						@Override
						public void onAnimationStart(Animation arg0) {}
					});
					titleIndicator.startAnimation(anim);
					
				}}, 800);
			}
			@Override
			public void onAnimationRepeat(Animation arg0) {}
			@Override
			public void onAnimationStart(Animation arg0) {}
		});
		titleIndicator.startAnimation(anim);
		
    	

		
		
    	_messagesGetInbox = !_messagesGetInbox;
    	mPager.getAdapter().notifyDataSetChanged();
    }
    public boolean getMessageType()
    {
    	return _messagesGetInbox;
    }
    public MessageFragment getMessageFragment()
    {
    	/*
    	int mId = 3;
		if (!_showFavorites)
			mId = 2;
		
		FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
		MessageFragment mf = (MessageFragment) a.instantiateItem(mPager, mId);
		*/
		return _messageList;
    }
    public void refreshMessages()
    {
    	getMessageFragment()._adapter.triggerLoadMore();
    }
    public void clearMessages()
    {
    	getMessageFragment()._adapter.clear();
    }
    public void openSearch(Bundle args)
	{
    	if (_tviewFrame.isOpened() && !getDualPane())
    		_tviewFrame.closeLayer(true);
    	
    	_sresFrame.openLayer(true);
    	_appMenu.updateMenuUi();
    	_searchResults.openSearch(args, this);
		System.out.println("recvd call for search");
		hideKeyboard();
	}
	public void openSearchLOL(Bundle args)
	{
		_sresFrame.openLayer(true);
		_appMenu.updateMenuUi();
    	_searchResults.openSearchLOL(args, this);
    	
    	
	          
		System.out.println("recvd call for searchlol");
		hideKeyboard();
	}
	public void openSearchDrafts()
	{
		_sresFrame.openLayer(true);
		_appMenu.updateMenuUi();
    	_searchResults.openSearchDrafts(this);
	}
	
	// HANDLE ORIENTATION
	
	@Override
	public void onConfigurationChanged (Configuration newConfig)
	{
		super.onConfigurationChanged(newConfig);
		evaluateDualPane(newConfig);
		dialogResizeInstance();
	}
	
	public void setThreadViewFullScreen (boolean set)
	{
		if (getDualPane())
		{
			this.findViewById(R.id.pagerContainer).setVisibility((set) ? View.GONE : View.VISIBLE);
			if (set)
				((RelativeLayout.LayoutParams)_tviewFrame.getLayoutParams()).width = this.getScreenWidth();
			else
				setDualPane(true);
		}
		
	}
	public boolean getThreadViewFullScreen()
	{
		return (findViewById(R.id.pagerContainer).getVisibility() == View.GONE);
	}
	public void evaluateDualPane(Configuration conf)
	{
        _splitView = Integer.parseInt(_prefs.getString("splitView", "1"));
       
        if (_orientLock != Integer.parseInt(_prefs.getString("orientLock", "0")))
        {
        	_orientLock = Integer.parseInt(_prefs.getString("orientLock", "0"));
	        if (_orientLock == 0)
	        	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
	        if (_orientLock == 1)
	        	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
	        if (_orientLock == 2)
	        	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
	        if (_orientLock == 3)
	        	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
	        if (_orientLock == 4)
	        	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        }
    
        if (_splitView == 0)
        {
        	setThreadViewFullScreen(false);
        	setDualPane(false);
        }
        else if (((_splitView == 1) && (conf.orientation == Configuration.ORIENTATION_LANDSCAPE)) || (_splitView == 2))
        {
        	setDualPane(true);
        }
        else
        {
        	setThreadViewFullScreen(false);
        	setDualPane(false);
        }
	}
	public boolean getDualPane () { return _dualPane; }
	public boolean getSliderOpen () { return _tviewFrame.isOpened(); }
	
	public void setDualPane (boolean dualPane)
	{
		SlideFrame slide = (SlideFrame)findViewById(R.id.singleThread);
		SlideFrame sres = (SlideFrame)findViewById(R.id.searchResults);
		ViewPager pager = (ViewPager)findViewById(R.id.pager);
		RelativeLayout pagerCont = (RelativeLayout)findViewById(R.id.pagerContainer);
		
		if (!dualPane)
		{
			// CHANGE TO NON DUAL PANE MODE 
			
			// sresults slider
			((RelativeLayout.LayoutParams)sres.getLayoutParams()).width = getScreenWidth();
			((RelativeLayout.LayoutParams)sres.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF, 0);
    		
			((RelativeLayout.LayoutParams)pagerCont.getLayoutParams()).width = getScreenWidth();
			((RelativeLayout.LayoutParams)pagerCont.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF,0);
    		pagerCont.requestLayout();
    		
    		// changee slider layer

    		((RelativeLayout.LayoutParams)slide.getLayoutParams()).width = getScreenWidth();
    		slide.requestLayout();
    		((RelativeLayout.LayoutParams)slide.getLayoutParams()).addRule(RelativeLayout.ALIGN_PARENT_LEFT);
    		((RelativeLayout.LayoutParams)slide.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF,0);

    		if (_threadView._rootPostId == 0 && _threadView._messageId == 0)
    		{
    			pager.setVisibility(View.VISIBLE);
    			slide.closeLayer(false);
    		}
    		else
    			pager.setVisibility(View.VISIBLE);
    			
    		if (_prefs.getBoolean("swipeDismiss", true)) 
    			{ slide.setSlidingEnabled(true); }
    		else
    			{ slide.setSlidingEnabled(false); }
    		
    		((RelativeLayout)pagerCont.getParent()).requestLayout();
		}
		else
		{
			// DUAL PANE SETUP
			
			// sresults slider
			((RelativeLayout.LayoutParams)sres.getLayoutParams()).width = (int)(getScreenWidth() * (1f / 3f));
			
			// threadview slider
    		((RelativeLayout.LayoutParams)pagerCont.getLayoutParams()).width = (int)(getScreenWidth() / 3);
    		
    		((RelativeLayout.LayoutParams)slide.getLayoutParams()).width = (int)(getScreenWidth() * (2f / 3f)) + 1;
    		
    		if (_swappedSplit)
    		{
	       		((RelativeLayout.LayoutParams)slide.getLayoutParams()).addRule(RelativeLayout.ALIGN_PARENT_LEFT);
	       		((RelativeLayout.LayoutParams)slide.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF,0);
	    		((RelativeLayout.LayoutParams)pagerCont.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF, R.id.singleThread);
	    		((RelativeLayout.LayoutParams)sres.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF, R.id.singleThread);
    		}
    		else
    		{
	       		((RelativeLayout.LayoutParams)slide.getLayoutParams()).addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
	    		((RelativeLayout.LayoutParams)slide.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF, R.id.pagerContainer);
	    		((RelativeLayout.LayoutParams)pagerCont.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF, 0);
	    		((RelativeLayout.LayoutParams)sres.getLayoutParams()).addRule(RelativeLayout.RIGHT_OF, 0);
    		}
    		slide.requestLayout();
    		slide.setSlidingEnabled(false);
    		slide.openLayer(false);
    		pager.setVisibility(View.VISIBLE);
    		((RelativeLayout)pagerCont.getParent()).requestLayout();
		}
		_dualPane = dualPane;
		_threadView.updateThreadViewUi();
		
		track("ui_action", "dual_pane", Boolean.toString(dualPane));
		if (_appMenu != null)
			_appMenu.updateMenuUi();
	}
	

	// HANDLE CLOSED ACTIVITIES RETURNING TO MAIN
    
    private int getScreenWidth() {
    	// calculate sizes
        Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        DisplayMetrics displaymetrics = new DisplayMetrics();
        display.getMetrics(displaymetrics);
		return (displaymetrics.widthPixels);
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	System.out.println("MAINACTIVITY: activity result recv R_OK=" +Activity.RESULT_OK + " reqCodes: PostThread OTV PR" + ThreadListFragment.POST_NEW_THREAD + " " + ThreadListFragment.OPEN_THREAD_VIEW + " " + ThreadViewFragment.POST_REPLY + " data: " + requestCode + " " + resultCode);
    	if (requestCode == ThreadListFragment.OPEN_PREFS)
    	{
    		
    		if (resultCode == PreferenceView.RESTART_APP)
    		{
    			Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
		        finish();
		        startActivity(i);
		        return;
    		}
    		
    		if (_prefs != null)
    		{
	    		_analytics  = _prefs.getBoolean("analytics", true);
	    		_zoom  = Float.parseFloat(_prefs.getString("fontZoom", "1.0"));
	    		_showFavorites  = _prefs.getBoolean("showFavorites", false);
	    		_showPinnedInTL  = _prefs.getBoolean("showPinnedInTL", true);
	    		_swappedSplit  = _prefs.getBoolean("swappedSplit", false);
	    		_enableKeywordFilter = _prefs.getBoolean("enableDonatorFeatures", false);
    		}
    		
	    		evaluateDualPane(getResources().getConfiguration());
	    	if (_threadView != null)
	    	{
	    		if (_threadView._adapter != null)
	    		{
		    		_threadView._adapter.loadPrefs();
		    		_threadView._adapter.notifyDataSetChanged();
	    		}
	    		
	    		/*
	    		FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
	    		ThreadListFragment TLfragment = (ThreadListFragment) a.instantiateItem(mPager, 1);
	    		*/
	    		if (_threadList._adapter != null)
	    		{
		    		_threadList._adapter.updatePrefs();
		    		_threadList._adapter.notifyDataSetChanged();
	    		}
	    		
	    		// SearchView svf = (SearchView) a.instantiateItem(mPager, 0);
	    		_searchView.setupBasicSearchList();
	    		
	    		_appMenu.updateMenuUi();
    		}
    	}
    	if (requestCode == ThreadListFragment.POST_NEW_THREAD)
    	{
    		if (resultCode == Activity.RESULT_OK)
            {
                // read the resulting thread id from the post
                int postId = data.getExtras().getInt("postId");
                
                // hey, thats the same thing I just wrote!
                openThreadViewAndFave(postId);
            }
    	}
    	if (requestCode == ThreadViewFragment.POST_REPLY)
    	{
            if (resultCode == Activity.RESULT_OK)
            {
                // read the resulting thread id from the post
            	// this is either the id of your new post or the id of the post your replied t
                
                // ThreadViewFragment TVf = (ThreadViewFragment)getSupportFragmentManager().findFragmentById(R.id.singleThread);
                if (_threadView != null)
                	_threadView.onActivityResult(requestCode, resultCode, data);
            }
        }
    	if (requestCode == ThreadViewFragment.POST_MESSAGE)
    	{
            if (resultCode == Activity.RESULT_OK)
            {
            	AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Message Sent");
                builder.setMessage("ShackMessage was successfully sent.");
                builder.setNegativeButton("OK", null);
                builder.create().show();
            }
            
        }

    }
    
    public void addToThreadIdBackStack (int threadId)
    {
    	_threadIdBackStack.add(threadId);
    }
    public void resetThreadIdBackStack ()
    {
    	_threadIdBackStack = new ArrayList<Integer>();
    }
	
    @Override
    public boolean onKeyDown(int keycode, KeyEvent e) {
        switch(keycode) {
            case KeyEvent.KEYCODE_MENU:
                toggleMenu();
                return true;
        }

        return super.onKeyDown(keycode, e);
    }
    
	// back button overriding
	@Override
	public void onBackPressed() {
		if (isMenuOpen())
		{
			closeMenu();
		}
		else if (_nextBackQuitsBecauseOpenedAppViaIntent && !getDualPane ())
		{
			_nextBackQuitsBecauseOpenedAppViaIntent = false;
			_threadList._nextBackQuitsBecauseOpenedAppViaIntent = false;
			super.onBackPressed();
		}
		else if (_threadIdBackStack.size() > 0)
		{
			this.openThreadViewAndSelectWithBackStack(_threadIdBackStack.get(_threadIdBackStack.size() -1));
			_threadIdBackStack.remove(_threadIdBackStack.size() -1);
		}
		else if (getThreadViewFullScreen())
		{
			_threadView.toggleFullScreen();
		}
		else if (getSliderOpen() && !getDualPane())
		{
			_tviewFrame.closeLayer(true);
		}
		else if (_sresFrame.isOpened())
		{
			_sresFrame.closeLayer(true);
		}
		else if(mPager.getCurrentItem() == 0)
		{
			mPager.setCurrentItem(1, true);
		}
		else if (mPager.getCurrentItem() != 1)
		{
			mPager.setCurrentItem(1, true);
		}
		else if (getTLSearchBar().getVisibility() == View.VISIBLE)
		{
			hideFinder();
		}
		else
		{
			super.onBackPressed();
		}
	}
	
	// SET UP FRAGMENTS
	class SbFragmentAdapter extends FragmentPagerAdapter {	  
	    private int mCount = 4;

	    public SbFragmentAdapter(FragmentManager fm) {
	        super(fm);
	    }

	    @Override
	    public Fragment getItem(int position) {

	    	if (position == 0)
    		{
    			// show the input page
	    		return _searchView;
    		}
    		else if (position == 1)
    		{
    			// show the input page
	    		return _threadList;
    		}
    		else if ((position == 3) || (position == 2 && !_showFavorites))
    		{
    			// show the input page
	    		return _messageList;
    		}
	    	else if (_showFavorites)
	    	{
	    		Bundle args = new Bundle();
	    		return (Fragment) Fragment.instantiate(getApplicationContext(), OfflineThreadFragment.class.getName(), args);
	    	}
			return null;
	    		
	    }

	    @Override
	    public int getCount() {
	    	if (_showFavorites)
	    		return mCount;
	    	else
	    		return mCount -1;
	    }

	    @Override
	    public CharSequence getPageTitle(int position) {
	      return pageIdToString(position);
	    }

	    public void setCount(int count) {
	        if (count > 0 && count <= 10) {
	            mCount = count;
	            notifyDataSetChanged();
	        }
	    }
	}
	
	
	// VOLUME KEY SCROLLING
	@Override
    public boolean dispatchKeyEvent(KeyEvent event)
    {
		/*
		ThreadViewFragment TVfragment = (ThreadViewFragment)getSupportFragmentManager().findFragmentById(R.id.singleThread);
        
    	FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
		ThreadListFragment TLfragment = (ThreadListFragment) a.instantiateItem(mPager, 1);
        */
        Boolean handleVolume = _prefs.getBoolean("useVolumeButtons", true);
        
        // do not do volume scroll with open web browser
        if (handleVolume && _mOpenDialog == null)
        {
            if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP)
            {
                if (event.getAction() == KeyEvent.ACTION_DOWN)
                {
                    if ((_threadView != null) && (getDualPane() || getSliderOpen())) _threadView.adjustSelected(-1);
                    else if (_sresFrame.isOpened()) { _searchResults.adjustSelected(-1); }
                    else if (_threadList != null) _threadList.adjustSelected(-1);
                }
                return true;
            }
            else if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)
            {
                if (event.getAction() == KeyEvent.ACTION_DOWN)
                {
                	if ((_threadView != null) && (getDualPane() || getSliderOpen())) _threadView.adjustSelected(1);
                	else if (_sresFrame.isOpened()) { _searchResults.adjustSelected(1); }
                    else if (_threadList != null) _threadList.adjustSelected(1);
                }
                return true;
            }
        }
        return super.dispatchKeyEvent(event);
    }
	
	// dialog rotation stuff
	public Dialog dialogGetInstance()
	{
		_mOpenDialog = new Dialog(this, R.style.fullScreenDialog);
		_mOpenDialog.setOnCancelListener(new Dialog.OnCancelListener(){

			@Override
			public void onCancel(DialogInterface arg0) {
				// TODO Auto-generated method stub
				dialogCancelInstance();
			}});
		return _mOpenDialog;
	}
	public void dialogCancelInstance()
	{
		if (_mOpenDialog != null)
		{
			// cancel any playing videos
			WebView wb = (WebView)_mOpenDialog.findViewById(R.id.webView);
			wb.loadUrl("");
			try {
				WebView.class.getMethod("onPause").invoke(wb);
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			// make it known that it is gone
		}
		_mOpenDialog = null;
	}
	
	public void dialogResizeInstance()
	{
		if (_mOpenDialog != null)
    	{
			// calculate sizes
	        Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
	        DisplayMetrics displaymetrics = new DisplayMetrics();
	        display.getMetrics(displaymetrics);
	        int width = (int) Math.floor(displaymetrics.widthPixels - (20*(displaymetrics.xdpi / 160)));
	        // px = dp * (dpi / 160) according to android docs. so to use dips, use formula
	        int height = (int) Math.floor(displaymetrics.heightPixels - ( 105 * (displaymetrics.ydpi / 160) ));
	        /*
	        LinearLayout linLayout = (LinearLayout)_mOpenDialog.findViewById(R.id.linLayoutWebView);
	        linLayout.setLayoutParams(new LinearLayout.LayoutParams(width, height));
	        WebView wb = (WebView)linLayout.findViewWithTag("webview_tag");
	        wb.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, height)); */
    	}
	}
	
	/*
	 * CHECK FOR SHACKMESSAGES
	 */
	class CheckForSMTask extends AsyncTask<String, Void, Integer>
	{
	    Exception _exception;
	    String username;
	    String text;
	    int nlsid;
	    
        @Override
        protected Integer doInBackground(String... params)
        {
            try
            {
            	boolean verified = _prefs.getBoolean("usernameVerified", false);
                if (verified)
                {
	            	ArrayList<Message> msgs = ShackApi.getMessages(0, MainActivity.this);
	            	int unreadCount = 0;
	            	for (int i = 0; i < msgs.size(); i++)
	            	{
	            		if (msgs.get(i).getRead() == false)
	            		{
	            			if (unreadCount == 0)
	            			{
		            			username = msgs.get(i).getUserName();
		            			text = msgs.get(i).getRawContent();
		            			nlsid = msgs.get(i).getMessageId();
	            			}
	            			unreadCount++;
	            		}
	            	}
	            	return unreadCount;
            	}
                return 0;
            }
            catch (Exception e)
            {
                Log.e("shackbrowse", "Error getting sms", e);
                _exception = e;
                return 0;
            }
        }
        
        @Override
        protected void onPostExecute(Integer result)
        {
            if (_exception != null)
            {
            	System.out.println("SMget: err");
                ErrorDialog.display(MainActivity.this, "Error", "Error getting SMs:\n" + _exception.getMessage());
            }
            else if (result == null)
            {
            	System.out.println("SMget: err");
                ErrorDialog.display(MainActivity.this, "Error", "Unknown SM-related error.");
            }
            else
            {
            	if (result == 1)
            		sendSMBroadcast(username, text, nlsid, false, 1);
            	else if (result > 1)
            		sendSMBroadcast("multiple", "", nlsid, true, result);
            }
        }
	}
	
	/*
	 * LIMES
	 */
	class LimeTask extends AsyncTask<String, Void, String>
	{
	    Exception _exception;
	    
        @Override
        protected String doInBackground(String... params)
        {
            try
            {
            	return ShackApi.getLimes();
            }
            catch (Exception e)
            {
                Log.e("shackbrowse", "Error getting limes", e);
                _exception = e;
                return null;
            }
        }
        
        @Override
        protected void onPostExecute(String result)
        {
            if (_exception != null)
            {
            	System.out.println("limeget: err");
                ErrorDialog.display(MainActivity.this, "Error", "Error getting limes:\n" + _exception.getMessage());
            }
            else if (result == null)
            {
            	System.out.println("limeget: err");
                ErrorDialog.display(MainActivity.this, "Error", "Unknown lime-related error.");
            }
            else
            {
            	SharedPreferences.Editor editor = _prefs.edit();
            	editor.putString("limeUsers", result);
            	editor.commit();
            }
        }
	}
	/*
	 * Analytics
	 */
	
	@Override
	public void onStart() {
		super.onStart();
		EasyTracker.getInstance().activityStart(this); // Add this method.
		myTracker = EasyTracker.getTracker();
	}
	
	@Override
	public void onStop() {
		super.onStop();
		EasyTracker.getInstance().activityStop(this); // Add this method.
	}
	
	public void track (String category, String action, String label)
	{
		_analytics  = _prefs.getBoolean("analytics", true);
		if (_analytics && myTracker != null)
		{
			System.out.println("ANALYTICS: track " + category + action + label);
			myTracker.sendEvent(category, action, label, null);
		}
	}
	public void trackScreen (String screen)
	{
		_analytics  = _prefs.getBoolean("analytics", true);
		if (_analytics && myTracker != null)
		{
			System.out.println("ANALYTICS: screen " + screen);
			myTracker.sendView(screen);
		}
	}
	
	/*
	 * INTENTS (non-Javadoc)
	 * @see android.support.v4.app.FragmentActivity#onNewIntent(android.content.Intent)
	 */
	
	@Override
	protected void onNewIntent(Intent intent) {
	    setIntent(intent);
	    handleIntent(intent);
	}
	
	private void handleIntent(Intent intent) {
		// intent stuff
        String action = intent.getAction();
        String type = intent.getType();
        Uri uri = intent.getData();

        if (Intent.ACTION_SEND.equals(action) && type != null)
        {
            if ("text/plain".equals(type))
            {
            	String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
                if (sharedText != null) {
                    openComposer(ThreadListFragment.POST_NEW_THREAD, sharedText);
                }
            }
            else if (type.startsWith("image/"))
            {
            	Uri imageUri = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM);
                if (imageUri != null) {
                    // Update UI to reflect image being shared
                	openComposerAndUploadImage(ThreadListFragment.POST_NEW_THREAD, imageUri);
                }
            }
        }
        else if (Intent.ACTION_VIEW.equals(action) && uri != null)
    	{
    		String id = uri.getQueryParameter("id");
    		if (id == null)
    		{
    			ErrorDialog.display(this, "Error", "Invalid URL Found");
    			return;
    		}
    		else
    		{
    			_nextBackQuitsBecauseOpenedAppViaIntent = true;
    			_threadList._nextBackQuitsBecauseOpenedAppViaIntent = true;
    			openThreadViewAndSelect(Integer.parseInt(id));
    			_tviewFrame.setSlidingEnabled(false);
    			mPager.setVisibility(View.GONE);
    		}
    	}
        // external search intent      
        else if (Intent.ACTION_SEARCH.equals(action))
        {
	        String query = intent.getStringExtra(SearchManager.QUERY);
	        final Bundle args = new Bundle();
	        args.putString("terms", query);
        	openSearch(args);
        }
        
        // notifications
        Bundle extras = intent.getExtras();
        if (extras != null)
        {
        	for (String key: extras.keySet())
        	{
        	  Log.d ("wogglesb", key + " is a key in the bundle");
        	}
        	//  REPLY NOTIFICATIONS
	        if ((extras.containsKey("notificationOpenParentAuthorSearch")) || (extras.containsKey("notificationOpenId")))
	        {
	        	String noteNLSID = Integer.toString(extras.getInt("notificationNLSID"));
	        	// update local last seen
	        	Editor editor = _prefs.edit();
				editor.putString("GCMLastClickedId", noteNLSID);
				editor.commit();
				
				// update remote last seen
				_GCMAccess.doUpdTask(NetworkNotificationServers.UPDTASKTYPE_REPLY, noteNLSID);
				
				if (extras.containsKey("notificationOpenParentAuthorSearch"))
				{
		        	String username = _prefs.getString("userName", "").trim();
			        final Bundle args = new Bundle();
			        args.putString("parentAuthor", username);
			        args.putString("title", getResources().getString(R.string.search_repliestome));
			        
		        	openSearch(args);
		        	
		        	_searchResults.showNoResults(false);
				}
				else if (extras.containsKey("notificationOpenId"))
				{
					// search seen
		        	if (_searchResults != null && _searchResults._seen != null && _searchResults._seen._seenTable != null)
		        	{
			        	_searchResults._seen._seenTable.put(getResources().getString(R.string.search_repliestome).hashCode(), Integer.parseInt(noteNLSID));
			        	_searchResults._seen.store();
		        	}
		        	
		        	openThreadViewAndSelectWithBackStack(Integer.parseInt(noteNLSID));
				}
	        }
	        // VANITY NOTIFICATIONS
	        else if ((extras.containsKey("notificationOpenVanitySearch")) || (extras.containsKey("notificationOpenVanityId")))
	        {
	        	String noteNLSID = Integer.toString(extras.getInt("notificationNLSID"));
	        	// update local last seen
	        	Editor editor = _prefs.edit();
				editor.putString("GCMVanityLastClickedId", noteNLSID);
				editor.commit();
				
				// update remote last seen
				_GCMAccess.doUpdTask(NetworkNotificationServers.UPDTASKTYPE_VANITY, noteNLSID);
				
				// open search
				if (extras.containsKey("notificationOpenVanitySearch"))
				{
		        	String username = _prefs.getString("userName", "").trim();
			        final Bundle args = new Bundle();
			        args.putString("terms", username);
			        args.putString("title", getResources().getString(R.string.search_vanity));
			        
		        	openSearch(args);
		        	
		        	_searchResults.showNoResults(false);
				}
				// open post
				else if (extras.containsKey("notificationOpenVanityId"))
				{
					// search seen
		        	if (_searchResults != null && _searchResults._seen != null && _searchResults._seen._seenTable != null)
		        	{
			        	_searchResults._seen._seenTable.put(getResources().getString(R.string.search_vanity).hashCode(), Integer.parseInt(noteNLSID));
			        	_searchResults._seen.store();
		        	}
		        	
		        	openThreadViewAndSelectWithBackStack(Integer.parseInt(noteNLSID));
				}
	        }
	        // SHACKSM NOTIFICATIONS
	        else if (extras.containsKey("notificationOpenMessages"))
	        {
	        	String noteNLSID = Integer.toString(extras.getInt("notificationNLSID"));
	        	// update local last seen
	        	Editor editor = _prefs.edit();
				editor.putString("GCMShackMsgLastClickedId", noteNLSID);
				editor.commit();
				
				// update remote last seen
				_GCMAccess.doUpdTask(NetworkNotificationServers.UPDTASKTYPE_VANITY, noteNLSID);
				
				// open msgs
		        mPager.setCurrentItem(2);
	        }
        }
	}

	public boolean isMessagesShowing() {
		if (((mPager.getCurrentItem() == 3) && (_showFavorites)) || ((mPager.getCurrentItem() == 2) && (!_showFavorites)))
			return true;
		return false;
	}

	public void showFilters() {
		/*
		FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
		ThreadListFragment TLfragment = (ThreadListFragment) a.instantiateItem(mPager, 1);
		*/
		_threadList.showFilters();
	}
	public void showKeywords() {
		if (!_enableKeywordFilter )
		{
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
	        builder.setTitle("Donator Feature");
	        builder.setMessage("Enable this feature by clicking the menu, \"Unlock DLC\" and \"Access Donator Features\".");
	        builder.setPositiveButton("Go Now", new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int id) {
					Intent i = new Intent(MainActivity.this, DonateActivity.class);
	                startActivityForResult(i, ThreadListFragment.OPEN_PREFS);
	            }
	        });
	        builder.setNegativeButton("Cancel", null);
	        builder.create().show();
	        return;
		}
        
		/*FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
		ThreadListFragment TLfragment = (ThreadListFragment) a.instantiateItem(mPager, 1);*/
		_threadList.showFiltWordList();
	}
	public void hideFinder() {
		/*FragmentPagerAdapter a = (FragmentPagerAdapter) mPager.getAdapter();
		ThreadListFragment TLfragment = (ThreadListFragment) a.instantiateItem(mPager, 1);*/
		_threadList.hideFinder();
	}
	
	public View getTLSearchBar() {
		return findViewById(R.id.searchBarContainer);
	}
	
	// seen posts
	class Seen 
	{
		private static final int SEEN_HISTORY = 1000;
		private String SEEN_FILE = "seendb.cache";
		private Hashtable<Integer, Integer> _seenTable = null;
		Seen ()
		{
			_seenTable = load();
		}
		protected Hashtable<Integer, Integer> getTable()
		{
			return _seenTable;
		}
	    protected Hashtable<Integer, Integer> load()
	    {
	        Hashtable<Integer, Integer> counts = new Hashtable<Integer, Integer>();
	
	        if (getFileStreamPath(SEEN_FILE).exists())
	        {
	            // look at that, we got a file
	            try {
	                FileInputStream input = openFileInput(SEEN_FILE);
	                try
	                {
	                    DataInputStream in = new DataInputStream(input);
	                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
	                    String line = reader.readLine();
	                    while (line != null)
	                    {
	                        if (line.length() > 0)
	                        {
	                        	if (line.contains("="))
	                        	{
		                            String[] parts = line.split("=");
		                            if (parts.length > 0)
		                            {
		                            	try
		                            	{
		                            		counts.put(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
		                            	}
		                            	catch (NumberFormatException e)
		                            	{ }
		                            }
	                        	}
	                        }
	                        line = reader.readLine();
	                    }
	                }
	                finally
	                {
	                    input.close();
	                }
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	
	        return counts;
	    }
	    void store() throws IOException
	    {
	        List<Integer> postIds = Collections.list(_seenTable.keys());
	        Collections.sort(postIds);
	        
	        // trim to last 1000 posts
	        if (postIds.size() > SEEN_HISTORY)
	            postIds.subList(postIds.size() - SEEN_HISTORY, postIds.size() - 1);
	
	        FileOutputStream output = openFileOutput(SEEN_FILE, Activity.MODE_PRIVATE);
	        try
	        {
	            DataOutputStream out = new DataOutputStream(output);
	            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
	
	            for (Integer postId : postIds)
	            {
	            	writer.write(postId + "=" + _seenTable.get(postId));
	                writer.newLine();
	            }
	            writer.flush();
	        }
	        finally
	        {
	            output.close();
	        }
	    }
	}
	
	
	private void upgradeDonatorPreferences() {
		// check for old style preferences
		if (
				(_prefs.getBoolean("enablePushNotificationsPref", false)) ||
				(_prefs.getBoolean("displayLolButton", false)) ||
				(_prefs.getBoolean("displayNWSSearch", false)) ||
				(_prefs.getBoolean("enableSaveSearch", false)) ||
				(_prefs.getBoolean("enableKeywordFilter", false)) ||
				(_prefs.getString("limeUsers", "").contains(_prefs.getString("userName", "")) && _prefs.getString("userName", "") != "")
			)
		{
			Editor edit = _prefs.edit();
			edit.putBoolean("enableDonatorFeatures", true);
			edit.commit();
		}
	}
	
	protected void onSaveInstanceState(Bundle save) {
		  super.onSaveInstanceState(save);
		  
		  
	}
	
	/*
	 * OFFLINE THREAD CHOOSE STUFF
	 * 
	 */
    // OFFLINE THREAD CLOUD STUFF
    public void cloudChoose()
    {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        
        boolean verified = prefs.getBoolean("usernameVerified", false);
        if (!verified)
        {
        	LoginForm login = new LoginForm(this);
        	login.setOnVerifiedListener(new LoginForm.OnVerifiedListener() {
				@Override
				public void onSuccess() {
					cloudChoose();
				}

				@Override
				public void onFailure() {
				}
			});
        	return;
        }
        
        boolean cloudEnabled = (this)._prefs.getBoolean("enableCloudSync", true);
    	if (!cloudEnabled)
    	{
    		AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Enable Cloud Sync");
            builder.setMessage("Cloud sync is disabled. Enable?");
            builder.setPositiveButton("Enable Cloud Sync", new DialogInterface.OnClickListener(){

				@Override
				public void onClick(DialogInterface dialog, int which) {
			        	SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
	    	        	SharedPreferences.Editor editor = prefs.edit();
	                	editor.putBoolean("enableCloudSync", true);
	                	editor.commit();
				}});
            builder.setNegativeButton("Cancel", null);
            AlertDialog alert = builder.create();
            alert.setCanceledOnTouchOutside(true);
            alert.show();
    	}
    	else
    	{
	    	AlertDialog.Builder builder = new AlertDialog.Builder(this);
	        builder.setTitle("Choose Cloud Action");
	        final CharSequence[] items = { "Change Sync Interval (<1kb)","Perform Cloud to Local Copy","Perform Local to Cloud Copy","Merge Cloud and Local","Disable Cloud Sync"};
	        builder.setItems(items, new DialogInterface.OnClickListener() {
	            public void onClick(DialogInterface dialog, int item) {
	            	if (item == 0)
	            	{
	            		cloudIntervalChoose();
	            	}
	                if (item == 1)
	                {
	                	_threadList._offlineThread.setVerboseNext();
	                	_threadList._offlineThread.triggerCloudToLocal();
	                }
	                if (item == 2)
	                {
	                	_threadList._offlineThread.setVerboseNext();
	                	_threadList._offlineThread.triggerLocalToCloud();
	                }
	                if (item == 3)
	                {
	                	_threadList._offlineThread.setVerboseNext();
	                	_threadList._offlineThread.triggerCloudMerge();
	                }
	                if (item == 4)
	                {
	                	SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
	    	        	SharedPreferences.Editor editor = prefs.edit();
	                	editor.putBoolean("enableCloudSync", false);
	                	editor.commit();
	                }
	                }});
	        AlertDialog alert = builder.create();
	        alert.setCanceledOnTouchOutside(true);
	        alert.show();
    	}
    }
	protected void cloudIntervalChoose() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Choose Cloud Interval");
        final CharSequence[] items = { "30 seconds","1 minute","2 minutes","5 minutes (default)","10 minutes"};
        builder.setItems(items, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int item) {
            	
            	int len = 30;
            	if (item == 1)
            		len = 60;
                if (item == 2)
                	len = 120;
                if (item == 3)
                	len = 300;
                if (item == 4)
                	len = 600;
                
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
	        	SharedPreferences.Editor editor = prefs.edit();
            	editor.putInt("cloudInterval", len);
            	editor.commit();
                }});
        AlertDialog alert = builder.create();
        alert.setCanceledOnTouchOutside(true);
        alert.show();
		
	}
}